﻿using System;
using System.Diagnostics;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using WindowsPhoneEssentials.Controls;
using WindowsPhoneEssentials.Helpers;
using WindowsPhoneMVC.Commands;
using WindowsPhoneMVC.Navigation;

namespace WindowsPhoneMVC.Controls
{
    public class PartialView : ContentControl, ISendLoadStatus
    {
        public PartialView()
        {
            Loaded += PartialViewLoaded;
            HorizontalAlignment = HorizontalAlignment.Stretch;
            VerticalAlignment = VerticalAlignment.Stretch;
            HorizontalContentAlignment = HorizontalAlignment.Stretch;
            VerticalContentAlignment = VerticalAlignment.Stretch;
        }

        #region public string Source
        public static readonly DependencyProperty SourceProperty =
            DependencyProperty.Register("Source", typeof (string), typeof (PartialView), new PropertyMetadata(default(string)));

        private LoadStatus loadStatus;

        public string Source
        {
            get { return (string) GetValue(SourceProperty); }
            set { SetValue(SourceProperty, value); }
        }
        #endregion

        #region public object ActionParameter
        public static readonly DependencyProperty ActionParameterProperty =
            DependencyProperty.Register("ActionParameter", typeof (object), typeof (PartialView), new PropertyMetadata(default(object)));

        public object ActionParameter
        {
            get { return GetValue(ActionParameterProperty); }
            set { SetValue(ActionParameterProperty, value); }
        }
        #endregion

        void PartialViewLoaded(object sender, RoutedEventArgs e)
        {
            if(Source == null)
            {
                Debug.WriteLine("You must specify a Source for a partial view");
                return;
            }

            var controlWithViewModelDc = this
                .AncestorsAndSelf<FrameworkElement>()
                .FirstOrDefault(c => c.DataContext is ViewModelBase);

            if (controlWithViewModelDc == null)
            {
                Debug.WriteLine("Cannot find a control with a ViewModelBase datacontext in the visual tree");
                return;
            }

            var viewModel = (ViewModelBase) controlWithViewModelDc.DataContext;

            string controller;
            string action;
            if (!Navigate.ParseCommand(Source, out controller, out action))
            {
                Debug.WriteLine("Unable to parse the command {0}", Source);
                return;
            }

            if (ReadLocalValue(ActionParameterProperty) == DependencyProperty.UnsetValue)
                viewModel.Navigator.InvokePartial(LoadComplete, controller, action);
            else
                viewModel.Navigator.InvokePartial(LoadComplete, controller, action, ActionParameter);
        }

        private void LoadComplete(bool success, UserControl content)
        {
            if (success)
            {
                Content = content;
                LoadStatus = LoadStatus.Loaded;
            }
            else
                LoadStatus = LoadStatus.Failed;
        }

        public LoadStatus LoadStatus
        {
            get { return loadStatus; }
            set
            {
                loadStatus = value;
                var handler = LoadStatusChanged;
                if (handler != null) handler(this, EventArgs.Empty);
            }
        }

        public event EventHandler LoadStatusChanged;
    }
}